{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-colab"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/pathwaycom/pathway/blob/main/examples/projects/from_jupyter_to_deploy/part1_jupyter_exploration.ipynb\" target=\"_parent\"><img src=\"https://pathway.com/assets/colab-badge.svg\" alt=\"Run In Colab\" class=\"inline\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "notebook-instructions"
      },
      "source": [
        "# Installing Pathway with Python 3.10+\n",
        "\n",
        "In the cell below, we install Pathway into a Python 3.10+ Linux runtime.\n",
        "\n",
        "> **If you are running in Google Colab, please run the colab notebook (Ctrl+F9)**, disregarding the 'not authored by Google' warning.\n",
        "> \n",
        "> **The installation and loading time is less than 1 minute**.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "pip-installation-pathway"
      },
      "outputs": [],
      "source": [
        "%%capture --no-display\n",
        "!pip install --prefer-binary pathway"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1",
      "metadata": {
        "lines_to_next_cell": 2
      },
      "source": [
        "# Part 1: Static data exploration in Jupyter\n",
        "This notebook is part of the first part of the tutorial [From interactive data exploration to deployment](/developers/user-guide/exploring-pathway/from-jupyter-to-deploy#part-1-static-data-exploration-in-jupyter)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "--2024-06-12 08:20:46--  https://gist.githubusercontent.com/janchorowski/e351af72ecd8d206a34763a428826ab7/raw/ticker.csv\r\n",
            "Resolving gist.githubusercontent.com (gist.githubusercontent.com)... "
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "185.199.111.133, 185.199.109.133, 185.199.108.133, ...\r\n",
            "Connecting to gist.githubusercontent.com (gist.githubusercontent.com)|185.199.111.133|:443... connected.\r\n",
            "HTTP request sent, awaiting response... "
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "200 OK\r\n",
            "Length: 1253370 (1.2M) [text/plain]\r\n",
            "Saving to: ‘ticker.csv’\r\n",
            "\r\n",
            "\r\n",
            "ticker.csv            0%[                    ]       0  --.-KB/s               "
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\r\n",
            "ticker.csv          100%[===================>]   1.19M  --.-KB/s    in 0.02s   \r\n",
            "\r\n",
            "2024-06-12 08:20:46 (50.0 MB/s) - ‘ticker.csv’ saved [1253370/1253370]\r\n",
            "\r\n"
          ]
        }
      ],
      "source": [
        "# Download CSV file\n",
        "!wget -nc https://gist.githubusercontent.com/janchorowski/e351af72ecd8d206a34763a428826ab7/raw/ticker.csv"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3",
      "metadata": {},
      "source": [
        "## Loading data"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "4",
      "metadata": {},
      "outputs": [],
      "source": [
        "import datetime\n",
        "\n",
        "import pathway as pw\n",
        "\n",
        "# To use advanced features with Pathway Scale, get your free license key from\n",
        "# https://pathway.com/features and paste it below.\n",
        "# To use Pathway Community, comment out the line below.\n",
        "pw.set_license_key(\"demo-license-key-with-telemetry\")\n",
        "\n",
        "fname = \"ticker.csv\"\n",
        "schema = pw.schema_from_csv(fname)\n",
        "data = pw.io.csv.read(fname, schema=schema, mode=\"static\")\n",
        "data"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "5",
      "metadata": {},
      "outputs": [],
      "source": [
        "data = data.with_columns(t=data.t.dt.utc_from_timestamp(unit=\"ms\"))\n",
        "data"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "6",
      "metadata": {},
      "outputs": [],
      "source": [
        "import bokeh.plotting\n",
        "\n",
        "\n",
        "def vwap_history(src):\n",
        "    fig = bokeh.plotting.figure(\n",
        "        height=400,\n",
        "        width=600,\n",
        "        title=\"Volume-weighted average price\",\n",
        "        x_axis_type=\"datetime\",\n",
        "    )\n",
        "    fig.line(\"t\", \"vwap\", source=src)\n",
        "    return fig"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "7",
      "metadata": {},
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "[2024-06-12T08:20:48]:INFO:Preparing Pathway computation\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "[2024-06-12T08:20:48]:INFO:CsvFilesystemReader-0: 0 entries (1 minibatch(es)) have been sent to the engine\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "[2024-06-12T08:20:48]:INFO:CsvFilesystemReader-0: 18329 entries (2 minibatch(es)) have been sent to the engine\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "[2024-06-12T08:20:48]:WARNING:CsvFilesystemReader-0: Closing the data source\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "WARNING:param.Column00136: Displaying Panel objects in the notebook requires the panel extension to be loaded. Ensure you run pn.extension() before displaying objects in the notebook.\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "[2024-06-12T08:20:49]:WARNING:Displaying Panel objects in the notebook requires the panel extension to be loaded. Ensure you run pn.extension() before displaying objects in the notebook.\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "Column\n",
              "    [0] Row\n",
              "        [0] Markdown(str)\n",
              "        [1] TooltipIcon(value='Immediate table p...)\n",
              "    [1] Bokeh(figure)"
            ]
          },
          "execution_count": null,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "data.plot(vwap_history, sorting_col=\"t\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8",
      "metadata": {},
      "source": [
        "## Designing the algorithm"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "9",
      "metadata": {},
      "outputs": [],
      "source": [
        "minute_20_stats = (\n",
        "    data.windowby(\n",
        "        pw.this.t,\n",
        "        window=pw.temporal.sliding(\n",
        "            hop=datetime.timedelta(minutes=1), duration=datetime.timedelta(minutes=20)\n",
        "        ),\n",
        "        instance=pw.this.ticker,\n",
        "    )\n",
        "    .reduce(\n",
        "        ticker=pw.this._pw_instance,\n",
        "        t=pw.this._pw_window_end,\n",
        "        volume=pw.reducers.sum(pw.this.volume),\n",
        "        transact_total=pw.reducers.sum(pw.this.volume * pw.this.vwap),\n",
        "        transact_total2=pw.reducers.sum(pw.this.volume * pw.this.vwap**2),\n",
        "    )\n",
        "    .with_columns(vwap=pw.this.transact_total / pw.this.volume)\n",
        "    .with_columns(\n",
        "        vwstd=(pw.this.transact_total2 / pw.this.volume - pw.this.vwap**2) ** 0.5\n",
        "    )\n",
        "    .with_columns(\n",
        "        bollinger_upper=pw.this.vwap + 2 * pw.this.vwstd,\n",
        "        bollinger_lower=pw.this.vwap - 2 * pw.this.vwstd,\n",
        "    )\n",
        ")\n",
        "minute_20_stats"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "10",
      "metadata": {},
      "outputs": [],
      "source": [
        "minute_1_stats = (\n",
        "    data.windowby(\n",
        "        pw.this.t,\n",
        "        window=pw.temporal.tumbling(datetime.timedelta(minutes=1)),\n",
        "        instance=pw.this.ticker,\n",
        "    )\n",
        "    .reduce(\n",
        "        ticker=pw.this._pw_instance,\n",
        "        t=pw.this._pw_window_end,\n",
        "        volume=pw.reducers.sum(pw.this.volume),\n",
        "        transact_total=pw.reducers.sum(pw.this.volume * pw.this.vwap),\n",
        "    )\n",
        "    .with_columns(vwap=pw.this.transact_total / pw.this.volume)\n",
        ")\n",
        "minute_1_stats"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "11",
      "metadata": {},
      "outputs": [],
      "source": [
        "joint_stats = (\n",
        "    minute_1_stats.join(\n",
        "        minute_20_stats, pw.left.t == pw.right.t, pw.left.ticker == pw.right.ticker\n",
        "    )\n",
        "    .select(\n",
        "        *pw.left,\n",
        "        bollinger_lower=pw.right.bollinger_lower,\n",
        "        bollinger_upper=pw.right.bollinger_upper,\n",
        "    )\n",
        "    .with_columns(\n",
        "        is_alert=(\n",
        "            (pw.this.volume > 10000)\n",
        "            & (\n",
        "                (pw.this.vwap > pw.this.bollinger_upper)\n",
        "                | (pw.this.vwap < pw.this.bollinger_lower)\n",
        "            )\n",
        "        )\n",
        "    )\n",
        "    .with_columns(\n",
        "        action=pw.if_else(\n",
        "            pw.this.is_alert,\n",
        "            pw.if_else(pw.this.vwap > pw.this.bollinger_upper, \"sell\", \"buy\"),\n",
        "            \"hodl\",\n",
        "        )\n",
        "    )\n",
        ")\n",
        "joint_stats"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "12",
      "metadata": {},
      "outputs": [],
      "source": [
        "alerts = joint_stats.filter(pw.this.is_alert).select(\n",
        "    pw.this.ticker, pw.this.t, pw.this.vwap, pw.this.action\n",
        ")\n",
        "alerts"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "13",
      "metadata": {},
      "source": [
        "## Plotting Bollinger Bands"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "14",
      "metadata": {},
      "outputs": [],
      "source": [
        "import bokeh.models\n",
        "\n",
        "\n",
        "def stats_plotter(src):\n",
        "    actions = [\"buy\", \"sell\", \"hodl\"]\n",
        "    color_map = bokeh.models.CategoricalColorMapper(\n",
        "        factors=actions, palette=(\"#00ff00\", \"#ff0000\", \"#00000000\")\n",
        "    )\n",
        "\n",
        "    fig = bokeh.plotting.figure(\n",
        "        height=400,\n",
        "        width=600,\n",
        "        title=\"20 minutes Bollinger bands with last 1 minute average\",\n",
        "        x_axis_type=\"datetime\",\n",
        "    )\n",
        "\n",
        "    fig.line(\"t\", \"vwap\", source=src)\n",
        "\n",
        "    fig.line(\"t\", \"bollinger_lower\", source=src, line_alpha=0.3)\n",
        "    fig.line(\"t\", \"bollinger_upper\", source=src, line_alpha=0.3)\n",
        "    fig.varea(\n",
        "        x=\"t\",\n",
        "        y1=\"bollinger_lower\",\n",
        "        y2=\"bollinger_upper\",\n",
        "        fill_alpha=0.3,\n",
        "        fill_color=\"gray\",\n",
        "        source=src,\n",
        "    )\n",
        "\n",
        "    fig.scatter(\n",
        "        \"t\",\n",
        "        \"vwap\",\n",
        "        size=10,\n",
        "        marker=\"circle\",\n",
        "        color={\"field\": \"action\", \"transform\": color_map},\n",
        "        source=src,\n",
        "    )\n",
        "\n",
        "    return fig\n",
        "\n",
        "\n",
        "joint_stats.plot(stats_plotter, sorting_col=\"t\")"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3 (ipykernel)",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.11.9"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
